home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / advanced97 / DISSOLVE.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  9.5 KB  |  444 lines

  1. /*
  2. ** An Example of dissolve, using stencil
  3. */
  4. #include <math.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include <stdlib.h>
  8. #include <GL/glut.h>
  9.  
  10. #ifdef _WIN32
  11. #define drand48() ((double)rand()/RAND_MAX)
  12. #endif
  13.  
  14. int winWidth = 512;
  15. int winHeight = 512;
  16.  
  17. /*
  18. ** Create a single component texture map
  19. */
  20. GLfloat *make_texture(int maxs, int maxt)
  21. {
  22.     int s, t;
  23.     static GLfloat *texture;
  24.  
  25.     texture = (GLfloat *)malloc(maxs * maxt * sizeof(GLfloat));
  26.     for(t = 0; t < maxt; t++) {
  27.     for(s = 0; s < maxs; s++) {
  28.         texture[s + maxs * t] = ((s >> 4) & 0x1) ^ ((t >> 4) & 0x1);
  29.     }
  30.     }
  31.     return texture;
  32. }
  33.  
  34. enum {SPHERE = 1, CONE};
  35.  
  36.  
  37.  
  38.  
  39. GLfloat angle = 0.f; /* angle of rotating object in  layer 0 */
  40.  
  41. enum {X, Y};
  42. GLboolean eraser = GL_FALSE;
  43. GLint layer = 1;
  44. GLint eraserpos[2] = {512/8, 512/12};
  45.  
  46. /* draw eraser and erase what's underneath */
  47.  
  48. GLubyte *eraserpix = 0;
  49. int erasersize = 0;
  50. int eraserWidth;
  51. int eraserHeight;
  52. void
  53. makeEraser(void)
  54. {
  55.   int i;
  56.   int x, y;
  57.   int dx, dy;
  58.   float d;
  59.  
  60.   eraserWidth = winWidth / 6;
  61.   eraserHeight = winHeight / 6;
  62.   erasersize = 4 * eraserWidth * eraserHeight;
  63.   eraserpix = (GLubyte *)realloc(eraserpix, erasersize * sizeof(GLubyte));
  64.                  
  65.  
  66.   /* make it not erase */
  67.   (void)memset(eraserpix, 0, erasersize * sizeof(GLubyte));
  68.   
  69.   i = 0;
  70.   for(y = 0; y < eraserHeight; y++)
  71.       for(x = 0; x < eraserWidth; x++)
  72.       {
  73.       dx = x - eraserWidth / 2;
  74.       dy = y - eraserHeight / 2;
  75.       d = sqrt(dx * dx + dy * dy);
  76.           if(pow(drand48(), .75) * eraserWidth / 2 > d)
  77.       {
  78.           eraserpix[i + 0] = 255;
  79.           eraserpix[i + 1] = 255;
  80.           eraserpix[i + 2] = 255;
  81.           eraserpix[i + 3] = 255;
  82.       }
  83.       i += 4;
  84.       }
  85. }
  86.  
  87.  
  88. /* left button, first layer, middle button, second layer */
  89. /* ARGSUSED */
  90. void
  91. mouse(int button, int state, int x, int y)
  92. {
  93.   if(state == GLUT_DOWN) {
  94.       eraser = GL_TRUE;
  95.       if(button == GLUT_LEFT_BUTTON)
  96.     layer = 1;
  97.       else /* GLUT_MIDDLE: GLUT_RIGHT is for menu */
  98.     layer = 0;
  99.   } else { /* GLUT_UP */
  100.     eraser = GL_FALSE;
  101.   }
  102.   glutPostRedisplay();
  103. }
  104.  
  105.  
  106. enum {CLEAR}; /* menu choices */
  107. GLboolean clearstencil = GL_TRUE;
  108.  
  109. void
  110. menu(int choice)
  111. {
  112.   switch(choice) {
  113.   case CLEAR:
  114.     clearstencil = GL_TRUE;
  115.     break;
  116.   }
  117.   glutPostRedisplay();
  118. }
  119.  
  120. /* used to get current width and height of viewport */
  121. void
  122. reshape(int wid, int ht)
  123. {
  124.   glViewport(0, 0, wid, ht);
  125.   winWidth = wid;
  126.   winHeight = ht;
  127.   clearstencil = GL_TRUE;
  128.   makeEraser();
  129.   glutPostRedisplay();
  130. }
  131.  
  132.  
  133.  
  134. void
  135. draweraser(void)
  136. {
  137.   glMatrixMode(GL_PROJECTION);
  138.   glLoadIdentity();
  139.   gluOrtho2D(0, winWidth, 0, winHeight);
  140.  
  141.   glMatrixMode(GL_MODELVIEW);
  142.   glLoadIdentity();
  143.  
  144.   /* replace with this layer */
  145.   glStencilFunc(GL_ALWAYS, layer, 0);
  146.   glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
  147.   glDisable(GL_LIGHTING);
  148.   glDisable(GL_DEPTH_TEST);
  149.  
  150.   glEnable(GL_ALPHA_TEST);
  151.   glAlphaFunc(GL_NOTEQUAL, 0);
  152.   glRasterPos2i(eraserpos[X], eraserpos[Y]);
  153.   glBitmap(0, 0, 0.f, 0.f, -winWidth/8.f, -winHeight/12.f, 0);
  154.   glDrawPixels(eraserWidth, eraserHeight, GL_RGBA, GL_UNSIGNED_BYTE, eraserpix);
  155.   glDisable(GL_ALPHA_TEST);
  156. }
  157.  
  158.  
  159. void
  160. drawlayer2(void)
  161. {
  162.   glMatrixMode(GL_PROJECTION);
  163.   glLoadIdentity();
  164.   gluOrtho2D(0, winWidth, 0, winHeight);
  165.  
  166.   glMatrixMode(GL_MODELVIEW);
  167.   glLoadIdentity();
  168.  
  169.   glDisable(GL_LIGHTING);
  170.   glDisable(GL_DEPTH_TEST);
  171.   glEnable(GL_TEXTURE_2D);
  172.  
  173.   glBegin(GL_QUADS);
  174.   glTexCoord2i(0, 0);
  175.   glVertex2i(0, 0);
  176.   glTexCoord2i(1, 0);
  177.   glVertex2i(winWidth, 0);
  178.   glTexCoord2i(1, 1);
  179.   glVertex2i(winWidth, winHeight);
  180.   glTexCoord2i(0, 1);
  181.   glVertex2i(0, winHeight);
  182.   glEnd();
  183.  
  184.   glDisable(GL_TEXTURE_2D);
  185.  
  186.   if(glGetError()) /* to catch programming errors; should never happen */
  187.        printf("Oops! I screwed up my OpenGL calls somewhere\n");
  188.  
  189. }
  190.  
  191. void
  192. drawlayer1(void)
  193. {
  194.     /* material properties for objects in scene */
  195.     static GLfloat wall_mat[] = {1.f, 1.f, 1.f, 1.f};
  196.     static GLfloat lightpos[] = {50.f, 50.f, -320.f, 1.f};
  197.  
  198.     /* draw a perspective scene */
  199.     glMatrixMode(GL_PROJECTION);
  200.     glLoadIdentity();
  201.     glFrustum(-100., 100., -100., 100., 320., 640.); 
  202.     glMatrixMode(GL_MODELVIEW);
  203.     glLoadIdentity();
  204.  
  205.     /* turn on features */
  206.     glEnable(GL_DEPTH_TEST);
  207.     glEnable(GL_LIGHTING);
  208.     glEnable(GL_LIGHT0);
  209.  
  210.     /* place light 0 in the right place */
  211.     glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  212.  
  213.     /* remove back faces to speed things up */
  214.     glCullFace(GL_BACK);
  215.  
  216.     /*
  217.     ** Note: wall verticies are ordered so they are all front facing
  218.     ** this lets me do back face culling to speed things up.
  219.     */
  220.  
  221.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, wall_mat);
  222.  
  223.     /* floor */
  224.     /* make the floor textured */
  225.     glEnable(GL_TEXTURE_2D);
  226.  
  227.     /*
  228.     ** Since we want to turn texturing on for floor only, we have to
  229.     ** make floor a separate glBegin()/glEnd() sequence. You can't
  230.     ** turn texturing on and off between begin and end calls
  231.     */
  232.     glBegin(GL_QUADS);
  233.     glNormal3f(0.f, 1.f, 0.f);
  234.     glTexCoord2i(0, 0);
  235.     glVertex3f(-100.f, -100.f, -320.f);
  236.     glTexCoord2i(1, 0);
  237.     glVertex3f( 100.f, -100.f, -320.f);
  238.     glTexCoord2i(1, 1);
  239.     glVertex3f( 100.f, -100.f, -520.f);
  240.     glTexCoord2i(0, 1);
  241.     glVertex3f(-100.f, -100.f, -520.f);
  242.     glEnd();
  243.  
  244.     glDisable(GL_TEXTURE_2D);
  245.  
  246.     /* walls */
  247.  
  248.     glBegin(GL_QUADS);
  249.     /* left wall */
  250.     glNormal3f(1.f, 0.f, 0.f);
  251.     glVertex3f(-100.f, -100.f, -320.f);
  252.     glVertex3f(-100.f, -100.f, -520.f);
  253.     glVertex3f(-100.f,  100.f, -520.f);
  254.     glVertex3f(-100.f,  100.f, -320.f);
  255.  
  256.     /* right wall */
  257.     glNormal3f(-1.f, 0.f, 0.f);
  258.     glVertex3f( 100.f, -100.f, -320.f);
  259.     glVertex3f( 100.f,  100.f, -320.f);
  260.     glVertex3f( 100.f,  100.f, -520.f);
  261.     glVertex3f( 100.f, -100.f, -520.f);
  262.  
  263.     /* ceiling */
  264.     glNormal3f(0.f, -1.f, 0.f);
  265.     glVertex3f(-100.f,  100.f, -320.f);
  266.     glVertex3f(-100.f,  100.f, -520.f);
  267.     glVertex3f( 100.f,  100.f, -520.f);
  268.     glVertex3f( 100.f,  100.f, -320.f);
  269.  
  270.     /* back wall */
  271.     glNormal3f(0.f, 0.f, 1.f);
  272.     glVertex3f(-100.f, -100.f, -520.f);
  273.     glVertex3f( 100.f, -100.f, -520.f);
  274.     glVertex3f( 100.f,  100.f, -520.f);
  275.     glVertex3f(-100.f,  100.f, -520.f);
  276.     glEnd();
  277.  
  278.     glPushMatrix();
  279.     glTranslatef(-80.f, -80.f, -420.f);
  280.     glCallList(SPHERE);
  281.     glPopMatrix();
  282.  
  283.     glPushMatrix();
  284.     glTranslatef(-20.f, -100.f, -500.f);
  285.     glCallList(CONE);
  286.     glPopMatrix();
  287.  
  288.     if(glGetError()) /* to catch programming errors; should never happen */
  289.        printf("Oops! I screwed up my OpenGL calls somewhere\n");
  290. }
  291.  
  292.  
  293. void
  294. drawlayer0(void)
  295. {
  296.   static GLfloat lightpos[] = {50.f, 50.f, 0.f, 1.f};
  297.   glMatrixMode(GL_PROJECTION);
  298.   glLoadIdentity();
  299.   glOrtho(-50.f, 50.f, -50.f, 50.f, 0.f, 100.f);
  300.  
  301.   glMatrixMode(GL_MODELVIEW);
  302.   glLoadIdentity();
  303.   glTranslatef(0.f, 0.f, -50.f);
  304.   glRotatef(angle, 0.f, 1.f, 0.f);
  305.   glRotatef(90.f, 0.f, 0.f, 1.f);
  306.   glTranslatef(0.f, -25.f, 0.f);
  307.  
  308.   glEnable(GL_LIGHTING);
  309.   glEnable(GL_LIGHT0);
  310.   glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
  311.   glCullFace(GL_BACK);
  312.   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  313.  
  314.   glCallList(CONE);
  315.  
  316. }
  317.  
  318. void
  319. redraw(void)
  320. {
  321.   if(glutLayerGet(GLUT_NORMAL_DAMAGED) || 
  322.           clearstencil == GL_TRUE) {
  323.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
  324.     clearstencil = GL_FALSE;
  325.   } else
  326.     glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  327.  
  328.   glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
  329.  
  330.   glStencilFunc(GL_EQUAL, 2, (unsigned)~0);
  331.   drawlayer2();
  332.  
  333.   glStencilFunc(GL_EQUAL, 1, (unsigned)~0);
  334.   drawlayer1();
  335.  
  336.   glStencilFunc(GL_EQUAL, 0, (unsigned)~0);
  337.   drawlayer0();
  338.  
  339.   if(eraser)
  340.     draweraser();
  341.  
  342.   glutSwapBuffers();
  343. }
  344.  
  345. void
  346. idle(void)
  347. {
  348.   angle += 1.f;
  349.   glutPostRedisplay();
  350. }
  351.  
  352.  
  353. void
  354. passive(int x, int y)
  355. {
  356.  
  357.   eraserpos[X] = x;
  358.   eraserpos[Y] = winHeight - y;
  359. }
  360.  
  361.  
  362. void
  363. motion(int x, int y)
  364. {
  365.  
  366.   eraserpos[X] = x;
  367.   eraserpos[Y] = winHeight - y;
  368.  
  369.   glutPostRedisplay();
  370. }
  371.  
  372. /* ARGSUSED1 */
  373. void key(unsigned char key, int x, int y)
  374. {
  375.   switch(key) {
  376.   case '\033':
  377.     exit(0);
  378.   }
  379. }
  380.  
  381. const int TEXDIM = 256;
  382. GLfloat *tex = 0;
  383.  
  384. main(int argc, char *argv[])
  385. {
  386.     static GLfloat sphere_mat[] = {1.f, .5f, 0.f, 1.f};
  387.     static GLfloat cone_mat[] = {0.f, .5f, 1.f, 1.f};
  388.     GLUquadricObj *sphere, *cone, *base;
  389.  
  390.     glutInit(&argc, argv);
  391.     glutInitWindowSize(winWidth, winHeight);
  392.     glutInitDisplayMode(GLUT_DOUBLE|GLUT_STENCIL|GLUT_DEPTH);
  393.     (void)glutCreateWindow("dissolve");
  394.     glutDisplayFunc(redraw);
  395.     glutMouseFunc(mouse);
  396.     glutMotionFunc(motion);
  397.     glutPassiveMotionFunc(passive);
  398.     glutKeyboardFunc(key);
  399.     glutIdleFunc(idle);
  400.     glutReshapeFunc(reshape);
  401.  
  402.     glutCreateMenu(menu);
  403.     glutAddMenuEntry("Clear Stencil", CLEAR);
  404.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  405.  
  406.  
  407.     glNewList(SPHERE, GL_COMPILE);
  408.     /* make display lists for sphere and cone; for efficiency */
  409.     sphere = gluNewQuadric();
  410.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, sphere_mat);
  411.     gluSphere(sphere, 20.f, 20, 20);
  412.     gluDeleteQuadric(sphere);
  413.     glEndList();
  414.  
  415.     glNewList(CONE, GL_COMPILE);
  416.     cone = gluNewQuadric();
  417.     base = gluNewQuadric();
  418.     glRotatef(-90.f, 1.f, 0.f, 0.f);
  419.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cone_mat);
  420.     gluQuadricOrientation(base, GLU_INSIDE);
  421.     gluDisk(base, 0., 20., 20, 1);
  422.     gluCylinder(cone, 20., 0., 60., 20, 20);
  423.     gluDeleteQuadric(cone);
  424.     gluDeleteQuadric(base);
  425.     glEndList();
  426.  
  427.     makeEraser();
  428.  
  429.     /* load pattern for current 2d texture */
  430.     tex = make_texture(TEXDIM, TEXDIM);
  431.     glTexImage2D(GL_TEXTURE_2D, 0, 1, TEXDIM, TEXDIM, 0, GL_RED, GL_FLOAT, tex);
  432.     free(tex);
  433.  
  434.     glClearStencil(2);
  435.     glEnable(GL_STENCIL_TEST); /* used all the time */
  436.  
  437.     glEnable(GL_CULL_FACE);
  438.     glCullFace(GL_BACK);
  439.  
  440.     glutMainLoop();
  441.  
  442.     return 0;
  443. }
  444.